package priv.conceit.study.leetcode.medium;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Semaphore;

/**
 * 编号：1115
 * 交替打印FooBar
 * 基于信号量
 *
 * @description: <a href="https://leetcode-cn.com/problems/print-foobar-alternately/">
 * @return:
 * @author: conceit
 * @date: 2019/11/1 15:00
 */
public class PrintFoobarAlternately2 {
	private int n;
	Semaphore foo;
	Semaphore bar;

	/**
	 * 实现线程交替打印
	 * <p>
	 * Semaphore 实例化
	 *
	 * @param args
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws InterruptedException {
		PrintFoobarAlternately2 printFoobarAlternately = new PrintFoobarAlternately2(15);
		new Thread(() -> {
			try {
				printFoobarAlternately.foo(() -> System.out.println("foo"));
			} catch (InterruptedException | BrokenBarrierException e) {
				e.printStackTrace();
			}
		}).start();
		new Thread(() -> {
			try {
				printFoobarAlternately.bar(() -> System.out.println("bar"));
			} catch (InterruptedException | BrokenBarrierException e) {
				e.printStackTrace();
			}
		}).start();

	}

	public PrintFoobarAlternately2(int n) {
		this.n = n;
		//foo线程先执行
		foo = new Semaphore(1);
		//bar 线程先等待
		bar = new Semaphore(0);
	}

	public void foo(Runnable printFoo) throws InterruptedException, BrokenBarrierException {

		for (int i = 0; i < n; i++) {
			foo.acquire();
			printFoo.run();
			// printFoo.run() outputs "foo". Do not change or remove this line.
			bar.release();
		}
	}

	public void bar(Runnable printBar) throws BrokenBarrierException, InterruptedException {

		for (int i = 0; i < n; i++) {
			bar.acquire();
			printBar.run();
			// printBar.run() outputs "bar". Do not change or remove this line.
			foo.release();

		}
	}
}
